package seqlist.array;

import seqlist.SeqList;

import java.util.Arrays;
import java.util.NoSuchElementException;

/**
 * @author yuisama
 * @date 2023/03/09 20:57
 * 基于动态数组实现的线性表
 **/
public class MyArray<E> implements SeqList<E> {
    private Object[] elementData;
    // 保存当前线性表中真正保存的有效元素个数
    private int size;
    public MyArray() {
        this(10);
    }
    // 从外部传入一个数组长度进行初始化操作
    public MyArray(int size) {
        this.elementData = new Object[size];
    }
    @Override
    public void add(E element) {
        this.elementData[size] = element;
        size ++;
        if (size == elementData.length) {
            // 当前数组已满，需要进行扩容处理
            grow();
        }
    }
    // 对内部的数组进行扩容处理
    private void grow() {
        int oldLength = elementData.length;
        // 默认扩容为原来的一倍
        int newLength = oldLength << 1;
        // 将原数组中的所有内容拷贝到新数组中，超出的部分使用默认值来填充
        Object[] newArray = Arrays.copyOf(elementData,newLength);
        elementData = newArray;
    }

    @Override
    public void add(int index, E element) {
        // 1.判断用户传入的index是否合法~
        if (index < 0 || index > size) {
            throw new IllegalArgumentException("add index illegal!");
        }
        // index <= size
        if (index == size) {
            add(element);
            return;
        }
        // 0 <= index < size
        for (int i = size - 1; i >= index; i--) {
            elementData[i + 1] = elementData[i];
        }
        // 此时index位置空出，填入待插入的元素
        elementData[index] = element;
        size ++;
        if (size == elementData.length) {
            grow();
        }
    }

    @Override
    public E removeByIndex(int index) {
        // 1.index合法性校验
        if(!rangeCheck(index)) {
            throw new IllegalArgumentException("remove index illegal!");
        }
        E oldVal = (E) elementData[index];
        // 从待删除元素开始，将当前位置的值覆盖为下一个元素的值
        // 由于删除场景下索引不能取到size
        // 因此要保证代码中所有位置均不越界，i + 1 < size
        for (int i = index; i < size - 1; i++) {
            elementData[i] = elementData[i + 1];
        }
        // 维护一下size属性,最后多的那个元素不影响我们的使用~下次添加元素时就会自动覆盖掉~
        size --;
        return oldVal;
    }

    @Override
    public void removeByValue(E element) {
        // 从前向后遍历，碰到第一个值为待删除的元素时，删除该元素并返回 ~
        for (int i = 0; i < size; i++) {
            if (elementData[i].equals(element)) {
                // 碰到第一个待删除的元素
                removeByIndex(i);
                return;
            }
        }
        System.out.println("没有待删除的元素!");
    }

    @Override
    public void removeAllValue(E element) {
        // 从前向后遍历，碰到索引对应的元素为待删除的元素，删除即可
        for (int i = 0; i < size;) {
            if (elementData[i].equals(element)) {
                // 当i指向的元素是待删除的元素，不能移动i
                removeByIndex(i);
            }else {
                // 此时i指向的不是待删除元素，此时移动i的指向,继续判断下一个元素是否是待删除的元素
                i ++;
            }
        }
    }

    @Override
    public E set(int index, E element) {
        if(!rangeCheck(index)) {
            throw new IllegalArgumentException("set index illegal!");
        }
        E oldVal = (E) elementData[index];
        elementData[index] = element;
        return oldVal;
    }

    @Override
    public E get(int index) {
        if (!rangeCheck(index)) {
            throw new IllegalArgumentException("get index illegal!");
        }
        return (E) elementData[index];
    }

    private boolean rangeCheck(int index) {
        if (index < 0 || index >= size) {
            return false;
        }
        return true;
    }

    @Override
    public boolean contains(E element) {
        // foreach会遍历所有的数组元素，包括无效元素！
        // 无效元素此时为null
//        for (Object e : elementData) {
//            if (e.equals(element)) {
//                return true;
//            }
//        }
        for (int i = 0; i < size; i++) {
            if (elementData[i].equals(element)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public int indexOf(E element) {
        for (int i = 0; i < size; i++) {
            if (elementData.equals(element)) {
                return i;
            }
        }
        throw new NoSuchElementException("indexOf error!" +
                "Don't has this element");
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder("[");
        // 遍历elementData数组
        for (int i = 0; i < size; i++) {
            sb.append(elementData[i]);
            if (i < size - 1) {
                sb.append(", ");
            }
        }
        sb.append("]");
        return sb.toString();
    }
}